﻿
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;

namespace gisgeb.comserver
{
    /// <summary>
    /// In Win32, a HDROP type contains a handle to an internal structure describing the group
    /// of files dropped during a drag-and-drop operation. The same format is used to pack the names
    /// of the selected files the user right-clicked on.
    /// </summary>
    internal class Hdrop
    {
        /// <summary>
        /// Retrieves the names of dropped files that result from a successful drag-and-drop operation.
        /// <see cref="http://msdn.microsoft.com/en-us/library/bb776408%28VS.85%29.aspx" />
        /// </summary>
        /// <param name="hDrop">Identifier of the structure that contains the file names of the dropped files.</param>
        /// <param name="iFile">Index of the file to query.
        /// If the value of this parameter is 0xFFFFFFFF, DragQueryFile returns a count of the files dropped. 
        /// If the value of this parameter is between zero and the total number of files dropped, 
        /// DragQueryFile copies the file name with the corresponding value to the buffer pointed to by the 
        /// lpszFileBuffer parameter.</param>
        /// <param name="lpszFileBuffer">The address of a buffer that receives the file name of a dropped 
        /// file when the function returns. This file name is a null-terminated string. 
        /// If this parameter is NULL, DragQueryFile returns the required size, in characters, of this buffer.</param>
        /// <param name="cch">The size, in characters, of the lpszFile buffer.</param>
        /// <returns></returns>
        [DllImport("shell32.dll", EntryPoint = "DragQueryFile")]
        private static extern uint DragQueryFile(uint hDrop,uint iFile, StringBuilder lpszFileBuffer, int cch);
        
        internal Hdrop(uint handle)
        {
            this.Win32Handle = handle;
        }
        
        internal uint Win32Handle
        {get; private set;}
        
        internal int GetNumberOfFiles()
        {
            return checked((int)DragQueryFile(this.Win32Handle, 0xffffffff, null, 0));
        }
        
        internal string GetFileNameForFileNumber(int number)
        {
            int neededSize = (int)DragQueryFile(this.Win32Handle, checked((uint)number), null, 0);
            StringBuilder sb = new StringBuilder(neededSize);
            DragQueryFile(this.Win32Handle, checked((uint)number), sb, neededSize + 1);
            return sb.ToString();
        }
        
        internal IEnumerable<string> GetFileNames()
        {
            int numberOfFiles = this.GetNumberOfFiles();
            for (int number = 0; number < numberOfFiles; number++)
            {
                yield return this.GetFileNameForFileNumber(number);
            }
        }
    }
}
